package com.inspection.service.impl;

import com.google.common.collect.Lists;
import com.inspection.dao.SysConfigDao;
import com.inspection.entity.SysConfigDO;
import com.inspection.model.dto.SysConfigDTO;
import com.inspection.model.dto.SysConfigQueryDTO;
import com.inspection.model.excel.SysConfigExcelVO;
import com.inspection.service.SysConfigService;
import com.inspection.support.AssertUtils;
import com.inspection.support.ExcelUtils;
import com.inspection.support.PageHelper;
import com.inspection.support.SortHelper;
import com.inspection.support.model.BusinessBaseException;
import com.inspection.support.model.KeyValuePair;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.persistence.criteria.Predicate;
import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class SysConfigServiceImpl implements SysConfigService {








    @Autowired
    private SysConfigDao sysConfigDao;
    @Override
    public Page<SysConfigDO> pageSysConfig(SysConfigQueryDTO query) {
        Sort sort = SortHelper.buildSort(query);

        PageHelper check = PageHelper.check(query.getPageNo(), query.getPageSize());
        Pageable pageable = PageRequest.of(check.getOffset(), check.getPageSize(), sort);

        Page<SysConfigDO> configPage = sysConfigDao.findAll(buildSpecification(query), pageable);

        return configPage;
    }

    @Override
    public void saveSysConfig(SysConfigDTO save) {
        AssertUtils.nonNull(save.getConfigCode(),"configCode 不能为空");
        AssertUtils.nonNull(save.getConfigValue(),"configValue 不能为空");
        SysConfigDO configDO=new SysConfigDO();
        BeanUtils.copyProperties(save,configDO);
        configDO.setIsDel(0);
        configDO.setDateCreate(new Date());
        sysConfigDao.save(configDO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateSysConfig(SysConfigDTO update) {
        AssertUtils.nonNull(update.getId(),"配置id不能为空！");
        Optional<SysConfigDO> sysConfigOp = sysConfigDao.findById(update.getId());
        if(!sysConfigOp.isPresent()){
            throw new BusinessBaseException("配置不存在!");
        }
        SysConfigDO confUpdate = sysConfigOp.get();
        confUpdate.setConfigName(update.getConfigName());
        confUpdate.setConfigValue(update.getConfigValue());
        confUpdate.setRemark(update.getRemark());

        sysConfigDao.saveAndFlush(confUpdate);
    }

    @Override
    public Map<String,String> initSysConfig(SysConfigDTO save) {
        SysConfigDO sysConfigDO= new SysConfigDO();
        sysConfigDO.setIsDel(0);
        List<SysConfigDO> sysConfigDOS = sysConfigDao.findAll(Example.of(sysConfigDO));
        if(CollectionUtils.isEmpty(sysConfigDOS)){
            return new HashMap<>();
        }
        Map<String, String> configMap = sysConfigDOS.stream().collect(Collectors.toMap
                (SysConfigDO::getConfigCode, configDO -> configDO.getConfigValue(), (String v1, String v2) -> v1));
        return configMap;
    }

    @Override
    public SysConfigDO getSysConfig(SysConfigQueryDTO query) {
        if(Objects.isNull(query.getConfigCode())&&Objects.isNull(query.getId())){
            throw new BusinessBaseException("业务参数异常");
        }
        SysConfigDO confQuery = new SysConfigDO();
        confQuery.setIsDel(0);
        confQuery.setId(query.getId());
        confQuery.setConfigCode(query.getConfigCode());

        Optional<SysConfigDO> configOp = sysConfigDao.findOne(Example.of(confQuery));
        if (!configOp.isPresent()) {
            return null;
        }

        return configOp.get();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delSysConfig(SysConfigDTO del) {
        AssertUtils.nonNull(del.getId(),"配置id不能为空！");
        Optional<SysConfigDO> sysConfigOp = sysConfigDao.findById(del.getId());
        if(!sysConfigOp.isPresent()){
            throw new BusinessBaseException("配置不存在!");
        }
        SysConfigDO confUpdate = sysConfigOp.get();
        confUpdate.setIsDel(1);
        sysConfigDao.saveAndFlush(confUpdate);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void batchDelSysConfig(SysConfigDTO del) {
        AssertUtils.notEmpty(del.getIdList(),"配置idList不能为空！");
        List<SysConfigDO> configs = sysConfigDao.findAllById(del.getIdList());
        if(CollectionUtils.isEmpty(configs)){
            throw new BusinessBaseException("配置不存在!");
        }
        sysConfigDao.deleteInBatch(configs);
        

    }

    @Override
    public void exportSysConfig(SysConfigQueryDTO query, HttpServletResponse response) {
        List<SysConfigDO> configs = sysConfigDao.findAll(buildSpecification(query));
        if(CollectionUtils.isEmpty(configs)){
            throw new BusinessBaseException("暂无可以导出的数据");
        }

        List<SysConfigExcelVO> vos = new ArrayList<>();

        for (SysConfigDO config : configs) {
            SysConfigExcelVO vo = new SysConfigExcelVO();
            BeanUtils.copyProperties(config, vo);
            vos.add(vo);
        }
        ArrayList<KeyValuePair> pairs = new ArrayList<>();
        pairs.add(KeyValuePair.builder().key("id").value("ID").build());
        pairs.add(KeyValuePair.builder().key("configCode").value("配置码").build());
        pairs.add(KeyValuePair.builder().key("configName").value("配置名称").build());
        pairs.add(KeyValuePair.builder().key("configValue").value("配置值").build());
        pairs.add(KeyValuePair.builder().key("dateCreate").value("创建时间").build());
        pairs.add(KeyValuePair.builder().key("remark").value("备注").build());
        ExcelUtils.export("系统配置导出",vos,pairs,response);
    }


    protected Specification<SysConfigDO> buildSpecification(SysConfigQueryDTO query) {
        return (Specification<SysConfigDO>) (root, criteriaQuery, criteriaBuilder) -> {
            List<Predicate> predicates = Lists.newArrayList();
            if (!StringUtils.isEmpty(query.getConfigCode())) {
                predicates.add(criteriaBuilder.equal(root.get("configCode"), query.getConfigCode()));
            }
            if (!StringUtils.isEmpty(query.getConfigName())) {
                predicates.add(criteriaBuilder.like(root.get("configName"), "%" + query.getConfigName() + "%"));
            }

            predicates.add(criteriaBuilder.equal(root.get("isDel"), 0));


            return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
        };
    }
}
